const {DataUtils} = require('./data_utils');

const {bcostars} = require('../tars/TransactionTars');

const {ECDSAUtils} = require('../utils/ecdsa_util');
class TxUtils {
  //helper 方法，传入hex字符串（abi编码),解码为二进制，设置txdata的input字段,目标类型为binBuffer
  static set_txdata_input(txdata, inputs_hex) {
    //console.log("set_txdata_input",txdata,inputs_hex);
    var bindata = DataUtils.hexToArray(inputs_hex);
    txdata.input.readFromObject(Buffer.from(bindata));
  }
  /*将TransactionData 按自定义的方式序列化成二进制数组*/
  static build_txdata_stream(tx) {
    /*
        BCOSCPP SDK里按以下顺序和字节格式对TransactionData进行字节层面的连接，并算hash
        这样做（而不是采用tars stream)的方式，是考虑到效率，直接用hash实现的update方法，无需先序列化，再调hash，而产生了多余的内存拷贝
        (int32_t)version
        chainID.data()
        groupID.data()
        (int64_t)blockLimit
        nonce.data()
        to.data()
        input.data()
        abi.data()
         */
    var streambuffer = [];
    var buffer = DataUtils.int32ToBytes(tx.version);
    streambuffer.push(...buffer);
    streambuffer.push(...DataUtils.strToBytes(tx.chainID));
    streambuffer.push(...DataUtils.strToBytes(tx.groupID));
    var buffer = DataUtils.int64ToBytes(tx.blockLimit);
    streambuffer.push(...buffer);
    streambuffer.push(...DataUtils.strToBytes(tx.nonce));
    streambuffer.push(...DataUtils.strToBytes(tx.to));
    var buffer = DataUtils.bufferToBytes(tx.input);
    streambuffer.push(...buffer);
    streambuffer.push(...DataUtils.strToBytes(tx.abi));
    return streambuffer;
  }

  /**
   * 传入TransactionData, TxHash, 签名串，构建Transaction,
   * 即可以发给节点的、签过名的rawTransaction,二进制格式
   * bcos cpp sdk里的实现，就是tars直接序列化流了
   * tars::TarsOutputStream<tars::BufferWriter> output;
   *     _transaction.writeTo(output);
   */
  /*填充tx的字段值*/
  static set_transaction(txdata, txhash, signresult) {
    var tx = new bcostars.Transaction();
    tx.attribute = 0;
    tx.importTime = 0;
    tx.data = txdata;
    tx.dataHash.readFromObject(Buffer.from(txhash));
    tx.signature.readFromObject(Buffer.from(signresult));
    tx.extraData = '';
    return tx;
  }

  /*序列化输出tx*/
  static build_rawtransaction_stream(txdata, txhash, signresult) {
    var tx = this.set_transaction(txdata, txhash, signresult);
    var buffer = tx.toBinBuffer();
    //console.log(buffer);
    return DataUtils.bufferToBytes(buffer);
  }

  //创建raw transaction data,含签名流程，返回二进制结果
  static build_rawtransaction_by_txdata(txdata, privkey) {
    const txdatastream = this.build_txdata_stream(txdata);
    const txhash = ECDSAUtils.calc_hash(txdatastream);
    //const txhash_bytes = ethers.getBytes("0x"+txhash);
    const txhash_bytes = DataUtils.hexToArray(txhash);
    const sigresult = ECDSAUtils.sign(txhash_bytes, privkey);
    //console.log("sigresult:",sigresult);

    const rawtxdata = this.build_rawtransaction_stream(
      txdata,
      txhash_bytes,
      DataUtils.hexToArray(sigresult),
    );
    return rawtxdata;
    //const rawtxdata_hex = ethers.hexlify(rawtxdata)
    //return rawtxdata_hex;
  }
}

module.exports.TxUtils = TxUtils;
